from django.shortcuts import render,redirect,reverse
from django.http import HttpResponseForbidden,JsonResponse
from meiduo_mall.libs.response_code import RETCODE
from django.views import View
import re
from django.contrib.auth import login,logout
from .models import User
import logging
from django_redis import get_redis_connection
#注册接收数据、校验、贮存数据
class RegisterUser(View):
    def get(self,request):
        return render(request,'register.html')

    def post(self,request):
        #获取用户注册信息
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        sms_code = request.POST.get('sms_code')
        allow = request.POST.get('allow')
        #判断是否有数据，输入数据是否正确
        if not all([username,password,password2,mobile,sms_code,allow]):
            return HttpResponseForbidden('缺少必传参数')

        if not re.match('[a-zA-Z0-9_-]{5,20}',username):
            return HttpResponseForbidden('请输入5-20个字符的用户名')
        if not re.match('^[0-9A-Za-z]{8,20}',password):
            return HttpResponseForbidden('您输入的手机号格式不正确')
        if password != password2:
            return HttpResponseForbidden('两次密码不一致')
        if not re.match('^1[345789]\d{9}$',mobile):
            return HttpResponseForbidden('您输入的手机号格式不正确')
        if allow != 'on':
            return HttpResponseForbidden('请勾选用户协议')
        #获取短信验证码
        redis_connet = get_redis_connection('verify_code')
        sms_data = redis_connet.get('sms_%s' % mobile)
        if sms_data is None or sms_code != sms_data.decode():
            return HttpResponseForbidden('手机验证码错误')
        #保存数据
        try:
            user = User.objects.create_user(username = username,password=password,mobile=mobile)
        except Exception as e:
            #工程日记记录
            logger = logging.getLogger('django')
            logger.error(e)
            return render(request,'register.html',{'register_errmsg': '用户注册失败'})
        #状态保持,(如果注册成功需要重新登陆,不用记录登陆状态)
        login(request,user)#保存用户的ID到SESSION中记录他的登陆状态

        #注册成功进入首页并显示登录信息
        response = redirect('/')
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response
        #前端失去焦点事件发送axios,通过get请求发送用户名
        #获取用户名与数据库对比，要么有要么没有，返回数字1或者0

#用户名重复
class UserRegisterView(View):

    def get(self,request,username):
        #获取数据库username的数据,返回1或者0
        count = User.objects.filter(username=username).count()
        #给前端返回json数据格式,根据前端要求返回什么就是什么
        return JsonResponse({'count':count,'code':RETCODE.OK,'error_msg':'OK'})

#密码重复
class MobilRegisterView(View):
    def get(self,requset,mobile):
        count = User.objects.filter(mobile=mobile).count()
        return JsonResponse({'count':count,'code':RETCODE.OK,'error_msg':'OK'})

#登录页面
class LoginView(View):
    def get(self,request):
        return render(request,'login.html')
    def post(self,request):
        #获取数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        allo = request.POST.get('remembered')
        if all([username,password]) is False:
            return HttpResponseForbidden('缺少参数')
        #数据对比，从数据库中提取到的密码是私密的，所以用django的后端认证
        from django.contrib.auth import authenticate

        #数据对比,django验证密码的方法，认证通过返回true,不通过返回False
        # u = User.objects.get(username=username)
        #验证数据库密码与传进来的密码是否一致
        # u.check_password(password)


        #authticate认证一组凭据,默认认证username,password,认证通过返回一个user对象
        #用户名或者密码认证失败引发异常返回None

        #通
        user = authenticate(username=username,password=password)


        if user is None:
            return render(request,'login.html',{'account_errmsg':'用户名或密码错误'})

        #状态保持(1)
        login(request,user)#默认保持两周
        #如果不勾选记住登录,设置关闭浏览器即关闭
        if allo != 'on':
            request.session.set_expiry(0)

        #在首页展示登录信息,
        # response = redirect(reverse('contents:index'))

        # 当用户没登录就访问用户中心时返回登录页面, 这时的地址变成.. / login /?next = / info /
        # 需求：用户登录直接进入访问用户中心
        # 实现：获取字符串next的值, 重定向到该地址
        #get()第二个参数是默认值,前面的找不到时使用默认值
        response = redirect(request.GET.get('next','/'))

        #账号有可能是手机号或者用户名
        if username == user.mobile:
            response.set_cookie('username', user.mobile, max_age=3600 * 24 * 15)
        else:
            response.set_cookie('username',user.username,max_age=3600 * 24 * 15)
        return response
#多账号登录实现：创建utils模块

#退出登录
class LoginOutView(View):
    def get(self,request):

        logout(request)

        reponse = redirect(reverse('contents:index'))

        reponse.delete_cookie('username')
        
        return reponse


#展示用户中心：登录即可访问，每登录重定向登录页面
#方法一:缺点：登录验证逻辑很多地方都需要，所以该代码需要重复编码好多次。
# class UserInfo(View):
#     #django里面设置了判断用户是否登录的方法request.user.is_authenticate(),登录返回True,未登录返回False
#     def get(self,request):
#         if request.user.is_authenticated():
#             return render(request,'user_center_info.html')
#         else:
#             return redirect(reverse('users:login'))

#方法二：用django的装饰器login_requried装饰as_view()的返回值
#装饰类视图as_view的返回值
from django.contrib.auth.decorators import login_required
## urlpatterns = [
##     url(r'login/',login_required(vews.UserInfo.as_view()),name='info')
## ]
#类视图函数
# class UserInfo(View):
#     def get(self,request):
#         return render(request,'user_center_info.html')


# 方法三：定义View子类封装login_required装饰器
# ​LoginRequired(object)`依赖于视图类`View`，复用性很差。
# 重写View的as_view()方法
# class AsUserView(object):
#     # 静态方法
#     @classmethod
#     def as_view(cls, **initkwargs):
#         # 自定义as_view方法,调用父类的as_view()方法
#         view = super().as_view()
#
#         # 用login_required()装饰入口函数
#         from django.contrib.auth.decorators import login_required
#         return login_required(view)
# # 创建子类,继承父类AsUserView
# class UserInfo(AsUserView, View):
#     def get(self, request):
#         return render(request, 'user_center_info.html')


# 方法四：使用django封装号的minxins的LoginRequiredMixin类判断用户名是否登录
#继承mixins的LoginRequiredMixin类

from django.contrib.auth import mixins

# 方法四：使用django封装号的minxins的LoginRequiredMixin类判断用户名是否登录
class UserInfo(mixins.LoginRequiredMixin,View):
    def get(self,request):
        return render(request,'user_center_info.html')


